package com.aube.rvi.module;

import android.content.Context;

import com.aube.rvi.CommonDataLoader;
import com.aube.rvi.OnModulePreparedListener;
import com.aube.rvi.net.AubeError;
import com.aube.rvi.net.BasicNetwork;
import com.aube.rvi.net.FileRequest;
import com.aube.rvi.net.ResponseListener;
import com.aube.rvi.net.StringRequest;
import com.aube.rvi.util.Utils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.util.HashMap;

/**
 * Created by huyaonan on 16/10/20.
 */
public class ModuleManager {

    private static final String TAG = "ModuleManager";

    private static ModuleManager mInstance = null;
    private Context mContext;

    private HashMap<String, DLPluginPackage> mPluginMaps = new HashMap<>();

    private ModuleManager(Context context) {
        mContext = context;
    }

    public static final String API_ROUTE = "http://192.168.1.254/openapi2/router/rest2";//http://openapi.aube-tv.com/router/rest2

    public static ModuleManager getInstance(Context context){
        if(mInstance == null){
            mInstance = new ModuleManager(context.getApplicationContext());
        }
        return mInstance;
    }

    public void startPluginLoader(String url, String fileName, ResponseListener<String> mRequestListener) {
        FileRequest request = new FileRequest(url, mRequestListener);

        String pkgName = mContext.getPackageName().replace(".", "_");
        request.setFileTitle(pkgName + "_" + toApk(fileName));
        CommonDataLoader.getInstance(mContext).startHttpLoader(request);
    }

    public void release() {
        mInstance = null;
    }

    public void getModules(String videoId, final OnModulePreparedListener listener) {
        HashMap<String, String> params = new HashMap<>();
        params.put("method", "com.aube.video.theme");
        params.put("videoid", videoId);
        StringRequest request = new StringRequest(API_ROUTE, params, new ResponseListener<String>() {
            @Override
            public void onResponse(String response) {
                //parse string
                ModuleItem item = ModuleItem.parseResponse(response);
                if(item != null) {
                    loadPluginFile(item, listener);
                }
            }

            @Override
            public void onErrorResponse(AubeError error) {

            }

            @Override
            public void onStart() {

            }
        });
        CommonDataLoader.getInstance(mContext).startHttpLoader(request);
    }

    private String toApk(String name) {
        if(name.contains(".apk"))
            return name;
        if(name.contains(".")) {
            return name.substring(0, name.lastIndexOf(".")) + ".apk";
        } else {
            return name + ".apk";
        }
    }

    private void loadPluginFile(ModuleItem item, OnModulePreparedListener listener) {
        try {
            String pkgName = mContext.getPackageName().replace(".", "_");
            String fileName = pkgName + "_" + toApk(item.getFileName());
            Utils.Log(TAG, "load plugin..." + fileName);
            File destFile = BasicNetwork.newPluginFile(fileName);
            Utils.sysout("-----target file..." + destFile.getPath());
            if (destFile.exists()) {
                Utils.sysout("-----check file..." + item.getFileName());
                boolean verifyResult = FileMD5Verify.md5sum(destFile, item.md5);
                if (verifyResult) {
                    Utils.sysout("-----verify..." + fileName);
                    installPlugins(item, destFile.getPath(), listener);
                } else {
                    destFile.delete();
                    Utils.sysout("-----delete and start to download..." + fileName);
                    downloadPlugin(item, listener);
                }
            } else {
                if(!copyPluginFromAssets(item, listener)) {
                    Utils.Log(TAG, "load plugin..." + fileName + "___from network");
                    downloadPlugin(item, listener);
                } else {
                    Utils.sysout("-----copy from assets success..." + fileName);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            if(listener != null)
                listener.onFail();
        }
    }

    /**
     * 将episode_1.apk从assets文件夹拷贝到本地文件夹,同时文件名变为com_aube_xxx_episode_1.apk
     * @param item
     * @return
     */
    private boolean copyPluginFromAssets(ModuleItem item, OnModulePreparedListener listener) {
        try {
            String pkgName = mContext.getPackageName().replace(".", "_");
            String fileName = pkgName + "_" + item.getFileName();
            InputStream is = mContext.getAssets().open(item.getFileName());
            if(is == null)
                return false;
            File destFile = BasicNetwork.newPluginFile(fileName);
            FileOutputStream fos = new FileOutputStream(destFile);
            byte[] buffer = new byte[1024];
            while (true) {
                int len = is.read(buffer);
                if (len == -1) {
                    break;
                }
                fos.write(buffer, 0, len);
            }
            is.close();
            fos.close();

            installPlugins(item, destFile.getPath(), listener);

            Utils.Log(TAG, "load plugin..." + fileName + "_from assets success");

            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    private void downloadPlugin(final ModuleItem item, final OnModulePreparedListener listener) {
        startPluginLoader(item.download, item.getFileName(), new ResponseListener<String>() {
            @Override
            public void onResponse(String response) {
                boolean verifyResult = FileMD5Verify.md5sum(response, item.md5);
                if (verifyResult)
                    installPlugins(item, response, listener);

                Utils.Log(TAG, "plugin.." + item.packagename + " download success at:" + response + ", verify " + (verifyResult ? "success" : "fail"));
            }

            @Override
            public void onErrorResponse(AubeError error) {
            }

            @Override
            public void onStart() {

            }
        });
    }

    private synchronized void installPlugins(ModuleItem item, String path, OnModulePreparedListener listener) {
        Utils.sysout("install......." + item.themeCode);
        DLPluginPackage pkg = DLPluginManager.getInstance(mContext).loadApk(path, item.themeCode);
        mPluginMaps.put(item.themeCode, pkg);
        listener.onReady(pkg, item.packagename);
    }

    public DLLayout inflatePluginLayout(Context context, DLPluginPackage plgPgk, String clazzName) {
        try {
            System.out.println("---------------------classloader:" + plgPgk.classLoader);
            Class<?> localClass = plgPgk.classLoader.loadClass(clazzName);
            Constructor<?> localConstructor = localClass.getConstructor(new Class[]{Context.class});
            DLLayout instance = (DLLayout) localConstructor.newInstance(new Object[]{context});
            instance.injectPluginPackage(plgPgk);
            return instance;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

}
